package com.zkthink.ceres.promotion.controller;

import com.zkthink.base.R;
import com.zkthink.ceres.common.annotations.IgnoreTenant;
import com.zkthink.ceres.promotion.dto.PromotionAdminDTO;
import com.zkthink.ceres.promotion.dto.PromotionIdDTO;
import com.zkthink.ceres.promotion.dto.PromotionSaveDTO;
import com.zkthink.ceres.promotion.dto.PromotionUpdateDTO;
import com.zkthink.ceres.promotion.entity.Promotion;
import com.zkthink.ceres.promotion.service.PromotionAdminService;
import com.zkthink.ceres.promotion.vo.admin.PromotionAdminPageVO;
import com.zkthink.context.BaseContextHandler;
import com.zkthink.dozer.DozerUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


/**
 * <p>
 * 前端控制器 营销活动表
 * </p>
 *
 * @author kellen
 * @date 2020-06-16
 */
@Slf4j
@Validated
@RestController
@AllArgsConstructor
@RequestMapping("/promotion")
@Api(value = "Promotion", tags = "营销活动表")
//@PreAuth(replace = "promotion:")
public class PromotionController {


  private PromotionAdminService promotionAdminService;

  private DozerUtils dozerUtils;


  /**
   * 时间校验
   */
  public R timeCheck(Promotion model) {
    LocalDateTime nowTime = LocalDateTime.now();
    if (model.getActivityStartTime().isBefore(nowTime)) {
      return R.validFail("活动开始时间不能早于当前时间");
    }
    if (model.getApplyStartTime().isBefore(nowTime)) {
      return R.validFail("报名开始时间不能早于当前时间");
    }
    if (model.getActivityEndTime().isBefore(model.getActivityStartTime())) {
      return R.validFail("活动开始时间不能晚于活动结束时间");
    }
    if (model.getApplyEndTime().isBefore(model.getApplyStartTime())) {
      return R.validFail("报名开始时间不能晚于报名结束时间");
    }

    if (model.getActivityStartTime().isBefore(model.getApplyEndTime())) {
      return R.validFail("活动开始时间不能早于报名结束时间");
    }
    return R.successDef();
  }

  @ApiOperation("查询活动详情")
  @GetMapping("/query/{id}")
  public R<Promotion> query(@PathVariable("id") Long id) {
    return R.success(promotionAdminService.getById(id));
  }


  @ApiOperation("更新营销活动")
  @PostMapping("/updatePromotion")
  public R updatePromotion(@RequestBody PromotionUpdateDTO updateDTO) {
    //查询活动状态
    Promotion promotion = promotionAdminService.getById(updateDTO.getId());
    if (null == promotion) {
      return R.fail("活动不存在");
    }
    LocalDateTime now = LocalDateTime.now();
    //报名未开始时可以更改任何信息
    if (promotion.getApplyStartTime().isAfter(now)) {
      Promotion promotionEntity = dozerUtils.map(updateDTO, Promotion.class);
      //时间校验
      R result = this.timeCheck(promotionEntity);
      if (!result.getIsSuccess()) {
        return result;
      }
      return promotionAdminService.updatePromotion(promotionEntity);
    }
    //报名进行中时仅能更改报名结束时间和活动时间
    if (promotion.getApplyStartTime().isBefore(now) && promotion.getApplyEndTime().isAfter(now)) {

      promotion = Promotion.builder().id(updateDTO.getId())
          .applyStartTime(promotion.getApplyStartTime())
          .applyEndTime(updateDTO.getApplyEndTime())
          .activityStartTime(updateDTO.getApplyStartTime())
          .activityEndTime(updateDTO.getActivityEndTime()).build();
      //时间校验
      R result = this.timeCheck(promotion);
      if (!result.getIsSuccess()) {
        return result;
      }
      return promotionAdminService.updatePromotion(promotion);
    }
    //活动未开始和进行中时仅可编辑活动结束时间，其他信息都不可更改
    if (promotion.getApplyStartTime().isAfter(now) || (promotion.getActivityStartTime()
        .isBefore(now) && promotion.getApplyEndTime().isAfter(now))) {
      promotion = Promotion.builder().id(updateDTO.getId())
          .applyStartTime(promotion.getApplyStartTime())
          .applyEndTime(promotion.getApplyEndTime())
          .activityStartTime(promotion.getActivityStartTime())
          .activityEndTime(updateDTO.getActivityEndTime()).build();
      //时间校验
      R result = this.timeCheck(promotion);
      if (!result.getIsSuccess()) {
        return result;
      }
      return promotionAdminService.updatePromotion(promotion);
    }
    return R.validFail("该活动状态不允许修改");
  }


  @ApiOperation("新增营销活动")
  @PostMapping("/addPromotion")
  public R<Boolean> addPromotion(@RequestBody PromotionSaveDTO promotion) {
    //时间校验
    Promotion promotionEntity = dozerUtils.map(promotion, Promotion.class);
    R result = this.timeCheck(promotionEntity);
    if (!result.getIsSuccess()) {
      return result;
    }
    return promotionAdminService.addPromotion(promotionEntity);
  }

  @ApiOperation("后台查询营销活动列表")
  @PostMapping("/findAdminPromotionList")
  public R<PromotionAdminPageVO> findAdminPromotionList(@RequestBody PromotionAdminDTO req) {
    return promotionAdminService.findAdminPromotionList(req);
  }

  @ApiOperation("删除活动")
  @PostMapping("/delete")
  public R query(@RequestBody PromotionIdDTO idDTO) {
    //查询活动状态
    Promotion promotion = promotionAdminService.getById(idDTO.getId());
    if (null == promotion) {
      return R.fail("活动不存在");
    }
    LocalDateTime now = LocalDateTime.now();
    //报名未开始时可以删除
    if (promotion.getApplyStartTime().isBefore(now)) {
      return R.success(promotionAdminService.removeById(idDTO.getId()));
    }
    return R.validFail("此活动不允许删除");
  }

  @ApiOperation("结束活动")
  @PostMapping("/end")
  @IgnoreTenant
  public R end(@RequestBody PromotionIdDTO promotionIdDTO) {
    //查询活动状态
    Promotion promotion = promotionAdminService.getById(promotionIdDTO.getId());
    if (null == promotion) {
      return R.fail("活动不存在");
    }
    if (promotion.getActivityEndTime().isBefore(LocalDateTime.now())) {
      return R.fail("活动已结束");
    }
    promotionAdminService.endPromotion(new ArrayList<>(Arrays.asList(promotion.getId())), LocalDateTime.now());
    return R.success();
  }

}
